package com.xq.transaction;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

/**
 * @author xq
 * @version 1.0
 * @date 2021/4/28 11:29
 * @description 测试redis的事务 加锁
 */
public class TestRedisTransactionLock {
    /**
     * watch命令就是标记一个键，如果标记了一个键，在提交事务之前，该键被别人修改了，那么事务就会失败，
     * 这种情况通常在程序中重新在尝试一次。
     * @param args
     */
    public static void main(String[] args) {
        TestRedisTransactionLock lock = new TestRedisTransactionLock();
        System.out.println("main retValue：" + lock.transMethod());
    }

    /**
     * 首先标记了键balance，然后检查余额是否足够，不足就取消标记，并不做扣减；足够的话，就启动事务进行更新操作，
     * 如果在此期间键balance被其他人修改，那在提交事务时就会报错，程序中通常可以捕获这类错误在重新执行一次，直到成功。
     * @return
     */
    public boolean transMethod() {
        // 创建连接
        Jedis jedis = new Jedis("192.168.2.120", 6379);
        // 设置密码，有密码设置，所有服务器都没设置
        //jedis.auth("123456");
        int balance; // 可用余额
        int debt; // 欠余额
        int amtToSubtract = 10; // 实刷额度
        // 监控key
        jedis.watch("balance");
        // jedis.set("balance","5");
        balance = Integer.parseInt(jedis.get("balance"));
        if(balance < amtToSubtract) {
            // 取消监控
            jedis.unwatch();
            System.out.println("modify");
            jedis.close();
            return false;
        }else {
            System.out.println("********开启事务");
            Transaction multi = jedis.multi();
            multi.decrBy("balance",amtToSubtract);
            multi.incrBy("debt",amtToSubtract);
            System.out.println("********执行事务");
            multi.exec();
            balance =Integer.parseInt(jedis.get("balance"));
            debt =Integer.parseInt(jedis.get("debt"));
            System.out.println("balance：" + balance);
            System.out.println("debt：" + debt);
            jedis.close();
            return true;
        }

    }
}
